// ============================================================================
// Name : main.cpp
// Author : Emiliano R. Gudino
// Version : v0.1
// Description : This is the main of the function processor
// ============================================================================

#include <iostream>
#include <string>
#include <signal.h>
#include "socketConn.h"
#include "keyboardInput.h"
#include "processFunctions.h"

#define TOTAL_SOCKETS	5;

using namespace std;

void Signal_Callback_Handler(int signum);
void Error(const char *msg);

// Register used to implement STATUS & EVENTS
char status_byte_register;													// Report STATUS conditions that may be queried via IEEE-488
char service_request_enable;												// Is the mask to SBR register
char standard_event_status;													// Event reports register may be queried via *ESR? command
char standard_event_status_enable;											// Is the mask to ESR register

int main()
{
	// Register signal and signal handler
	signal(SIGTERM, Signal_Callback_Handler);
	signal(SIGKILL, Signal_Callback_Handler);
	signal(SIGQUIT, Signal_Callback_Handler);

	// Create an array of pointers to functions
	ptr_functions_type ptr_functions_array[TOTAL_CMDS_FUNCTIONS];
	Init_Functions_Ptr_Array(ptr_functions_array);

	// Semaphore that wait the parsing finish
	sem_t global_queue_count;
	sem_init(&global_queue_count, 0, 0);									// Reset the semaphore

	// Create a Socket_Conn object for each connection
	Socket_Conn connection[LOCAL_SOCKET_TOTAL];

	// Structures used to manage the commands and responses
	command_request_str command_request;
	command_response_str command_response;

	// Connect the local sockets
	connection[0].Connect(&global_queue_count, FASTCGI_SOCKET_FILENAME);
	connection[1].Connect(&global_queue_count, TCP_SOCKET_FILENAME);
	connection[2].Connect(&global_queue_count, TELNET_SOCKET_FILENAME);
	connection[3].Connect(&global_queue_count, SERIAL_SOCKET_FILENAME);
	Keyboard_In keyboar_input(&global_queue_count);


	while(1)
	{
	        // Waiting for new command
	        sem_wait(&global_queue_count);

		// This code is only for testing, using the keyboard
		if(keyboar_input.Get_Command(&command_request))
		{
			if(command_request.command_id <= TOTAL_CMDS_FUNCTIONS)			// If command is one of the defined commands
				ptr_functions_array[command_request.command_id] (&command_request, &command_response);	// Call the function that process this command
			else
			{
				command_response.response_type = RESPONSE_STRING;				// In case of receive a command that not have a function defined
				strcpy(command_response.response, "No valid command");		// These command is not a valid command
			}
			keyboar_input.Set_Response(&command_response);					// Send the response to the local socket
			continue;
		//	sem_wait(&global_queue_count);									// wait for a new command
		}
		// End code for keyboard testing

		// Search who of the connections have a new command
		for(int j = 0; j < LOCAL_SOCKET_TOTAL; j++)
		{
			if(connection[j].Get_Command(&command_request))
			{																// Get_Command() return true if have a command
				if(command_request.command_id <= TOTAL_CMDS_FUNCTIONS)		// If command is one of the defined commands
					ptr_functions_array[command_request.command_id] (&command_request, &command_response);	// Call the function that process this command
				else
				{
					command_response.response_type = RESPONSE_STRING;			// In case of receive a command that not have a function defined
					strcpy(command_response.response, "No valid command");	// These command is not a valid command
				}
				connection[j].Set_Response(&command_response);				// Send the response to the local socket

				break;
				//sem_wait(&global_queue_count);								// wait for a new command
			}
		}
	}

	return 0;
}

void Error(const char *msg)
{
	perror(msg);
	exit(1);
}

void Signal_Callback_Handler(int signum)
{
	printf("Caught signal %d\n", signum);

	// Cleanup and close up stuff here
	// Terminate program
	exit(signum);
}
